from django.http import JsonResponse, QueryDict
from django.views import View
from kubernetes import client, config
from libs import k8s
import os,json

class deployment_api(View):

    k8s.load_auth_config()
    apps_api = client.AppsV1Api()

    def get(self,request):
        search_key = request.GET.get('query')
        namespace = request.GET.get('namespace')

        data = []
        try:
            for item in self.apps_api.list_namespaced_deployment(namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                replicas = item.spec.replicas
                available_replicas = (0 if item.status.available_replicas is None else item.status.available_replicas)
                labels = item.metadata.labels
                selector = item.spec.selector.match_labels
                containers = {}
                for c in item.spec.template.spec.containers:
                    containers[c.name] = c.image
                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)
                d = {"name": name, "namespace": namespace, "replicas": replicas,
                      "available_replicas": available_replicas, "labels": labels, "selector": selector,
                      "containers": containers, "create_time": create_time}
                if search_key:
                    if search_key in name:
                        data.append(d)
                else:
                    data.append(d)
            code = 200
            msg = "查询成功"
        except Exception as e:
            print(e)
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "查询失败！"
            code = 500

        count = len(data)
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize', 10))  # 当前页的数据数量
        start = (page - 1) * limit
        end = page * limit
        data = data[start:end]

        res = {'code': code, 'msg': msg, 'count': count, 'data': data}
        return JsonResponse(res)
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data['namespace']
        image = data['image']
        registry_auth = data['registry_auth']
        command = data['command']
        container_command = command.split() if command else None
        replicas = data['replicas']
        # 处理标签
        labels = {}
        if data['labels']:
            try:
                for l in data['labels'].split(","):
                    k = l.split("=")[0]
                    v = l.split("=")[1]
                    labels[k] = v
            except Exception as e:
                res = {"code": 500, "msg": "标签格式错误！"}
                return JsonResponse(res)
        resources = data['resources']
        if resources == "0.5c1g":
            resources = client.V1ResourceRequirements(limits={"cpu":"0.5","memory":"1Gi"},
                                                      requests={"cpu":"250m","memory":"500Mi"})
        elif resources == "1c2g":
            resources = client.V1ResourceRequirements(limits={"cpu":"1","memory":"2Gi"},
                                                      requests={"cpu":"0.5","memory":"1Gi"})
        elif resources == "2c4g":
            resources = client.V1ResourceRequirements(limits={"cpu": "2", "memory": "4Gi"},
                                                      requests={"cpu": "1", "memory": "2Gi"})
        elif resources == "4c8g":
            resources = client.V1ResourceRequirements(limits={"cpu": "4", "memory": "8Gi"},
                                                      requests={"cpu": "2", "memory": "4Gi"})

        health_liveness = ''
        health_readiness = ''
        probe_config = ''
        if data['health'] and data["probe_method"]:
            for i in data['health']:
                if i == 'liveness':
                    health_liveness = 'liveness'  #存活探针
                elif i == 'readiness':
                    health_readiness = 'readiness'  #就绪探针

            method = data["probe_method"]
            path = data["probe_path"]
            port = int(data["probe_port"])
            command = data["probe_command"]

            if method == "httpGet":
                http_get = client.V1HTTPGetAction(path=path, port=port)
                probe_config = client.V1Probe(http_get=http_get, initial_delay_seconds=30, period_seconds=30)
            elif method == "tcpSocket":
                tcpsocket = client.V1TCPSocketAction(port=port)
                probe_config = client.V1Probe(tcp_socket=tcpsocket, initial_delay_seconds=30, period_seconds=30)
            elif method == "exec":
                exec = client.V1ExecAction(command=command)
                probe_config = client.V1Probe(_exec=exec, initial_delay_seconds=30, period_seconds=30)

        try:
            image_pull_secrets = [client.V1LocalObjectReference(name=registry_auth)] if registry_auth else None
            body = client.V1Deployment(
                api_version="apps/v1",
                kind="Deployment",
                metadata=client.V1ObjectMeta(name=name),
                spec=client.V1DeploymentSpec(
                    replicas=replicas,
                    selector={'matchLabels': labels},
                    template=client.V1PodTemplateSpec(
                        metadata=client.V1ObjectMeta(labels=labels),
                        spec=client.V1PodSpec(
                            image_pull_secrets=image_pull_secrets,
                            containers=[client.V1Container(
                                # https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.md
                                name="container",
                                image=image,
                                command=container_command,
                                resources=resources,
                                liveness_probe=probe_config if health_liveness else None,
                                readiness_probe=probe_config if health_readiness else None
                                # env=[{"name": "TEST", "value": "123"}, {"name": "DEV", "value": "456"}], # 设置环境变量
                            )]
                        )
                    ),
                )
            )
            self.apps_api.create_namespaced_deployment(namespace=namespace, body=body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "deployment已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def delete(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data.get('namespace')
        try:
            self.apps_api.delete_namespaced_deployment(namespace=namespace, name=name)
            code = 200
            msg = "删除成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "删除失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def put(self,request):
        # 扩容和缩容副本数
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data['namespace']
        replicas = int(data['replicas'])

        min_replicas = 1
        max_replicas = 20
        body = self.apps_api.read_namespaced_deployment(namespace=namespace, name=name)
        current_replicas = body.spec.replicas

        if replicas == current_replicas:
            code = 500
            msg = "副本数一致！"
        elif replicas > max_replicas:
            code = 500
            msg = "副本数设置过大！请联系管理员操作。"
        elif replicas < min_replicas:
            code = 500
            msg = "副本数不能设置为0！"
        elif replicas > current_replicas and replicas < max_replicas:
            body.spec.replicas = replicas  # 将新副本数覆盖旧的
            self.apps_api.patch_namespaced_deployment(name=name, namespace=namespace, body=body)
            code = 200
            msg = "扩容成功！"
        elif replicas < current_replicas and replicas >= min_replicas:
            body.spec.replicas = replicas  # 将新副本数覆盖旧的
            self.apps_api.patch_namespaced_deployment(name=name, namespace=namespace, body=body)
            code = 200
            msg = "缩容成功！"

        result = {'code': code, 'msg': msg}
        return JsonResponse(result)


class daemonset_api(View):

    k8s.load_auth_config()
    apps_api = client.AppsV1Api()

    def get(self,request):
        search_key = request.GET.get('query')
        namespace = request.GET.get('namespace')

        data = []
        try:
            for item in self.apps_api.list_namespaced_daemon_set(namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                desired_number = item.status.desired_number_scheduled
                available_number = item.status.number_available
                labels = item.metadata.labels
                selector = item.spec.selector.match_labels
                containers = {}
                for c in item.spec.template.spec.containers:
                    containers[c.name] = c.image
                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                d = {"name": name, "namespace": namespace, "labels": labels, "desired_number": desired_number,
                      "available_number": available_number,
                      "selector": selector, "containers": containers, "create_time": create_time}
                if search_key:
                    if search_key in name:
                        data.append(d)
                else:
                    data.append(d)
            code = 200
            msg = "查询成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:  #  400 格式错误，409 资源存在，403 没权限。
                msg = "没有访问权限！"
            else:
                msg = "查询失败！"
            code = 500

        count = len(data)
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize', 10))  # 当前页的数据数量
        start = (page - 1) * limit  # 获取切片的起始值
        end = page * limit # 获取切片的结束值
        data = data[start:end]

        res = {'code': code, 'msg': msg, 'count': count, 'data': data}
        return JsonResponse(res)
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data["name"]
        namespace = data["namespace"]
        image = data["image"]
        registry_auth = data["registry_auth"]
        command = data["command"]
        command = command.split() if command else None
        # 处理标签
        labels = {}
        if data["labels"]:
            try:
                for l in data["labels"].split(","):
                    k = l.split("=")[0]
                    v = l.split("=")[1]
                    labels[k] = v
            except Exception as e:
                res = {"code": 500, "msg": "标签格式错误！"}
                return JsonResponse(res)

        try:
            image_pull_secrets = [client.V1LocalObjectReference(name=registry_auth)] if registry_auth else None
            body = client.V1DaemonSet(
                api_version="apps/v1",
                kind="DaemonSet",
                metadata=client.V1ObjectMeta(name=name),
                spec=client.V1DaemonSetSpec(
                    selector=client.V1LabelSelector(
                        match_labels=labels
                    ),
                    template=client.V1PodTemplateSpec(
                        metadata=client.V1ObjectMeta(labels=labels),
                        spec=client.V1PodSpec(
                            image_pull_secrets=image_pull_secrets,
                            containers=[client.V1Container(
                                name="container",
                                image=image,
                                command=command
                            )]
                        )
                    )
                )
            )
            self.apps_api.create_namespaced_daemon_set(namespace=namespace, body=body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "daemonset已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def delete(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data['namespace']
        try:
            self.apps_api.delete_namespaced_daemon_set(namespace=namespace, name=name)
            code = 200
            msg = "删除成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "删除失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def put(self,request):
        # 更新
        pass


class statefulset_api(View):

    k8s.load_auth_config()
    apps_api = client.AppsV1Api()
    core_api = client.CoreV1Api()

    def get(self,request):
        search_key = request.GET.get('query')
        namespace = request.GET.get('namespace')

        data = []
        try:
            for item in self.apps_api.list_namespaced_stateful_set(namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                labels = item.metadata.labels
                selector = item.spec.selector.match_labels
                replicas = item.spec.replicas
                ready_replicas = ("0" if item.status.ready_replicas is None else item.status.ready_replicas)
                # current_replicas = sts.status.current_replicas
                service_name = item.spec.service_name
                containers = {}
                for c in item.spec.template.spec.containers:
                    containers[c.name] = c.image
                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                d = {"name": name, "namespace": namespace, "labels": labels, "replicas": replicas,
                      "ready_replicas": ready_replicas, "service_name": service_name,
                      "selector": selector, "containers": containers, "create_time": create_time}
                if search_key:
                    if search_key in name:  # 实现模糊匹配
                        data.append(d)
                else:
                    data.append(d)
            code = 200
            msg = "查询成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "查询失败！"
            code = 500

        count = len(data)
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize', 10))  # 当前页的数据数量
        start = (page - 1) * limit
        end = page * limit
        data = data[start:end]

        res = {'code': code, 'msg': msg, 'count': count, 'data': data}
        return JsonResponse(res)
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data["name"]
        namespace = data["namespace"]
        image = data["image"]
        registry_auth = data["registry_auth"]
        command = data["command"]
        command = command.split() if command else None
        replicas = data['replicas']
        # 处理标签
        labels = {}
        if data["labels"]:
            try:
                for l in data["labels"].split(","):
                    k = l.split("=")[0]
                    v = l.split("=")[1]
                    labels[k] = v
            except Exception as e:
                res = {"code": 500, "msg": "标签格式错误！"}
                return JsonResponse(res)
        service_port = int(data["service_port"])
        service_target_port = int(data["service_target_port"])

        try:
            svc_body = client.V1Service(
                api_version="v1",
                kind="Service",
                metadata=client.V1ObjectMeta(
                    name=name
                ),
                spec=client.V1ServiceSpec(
                    cluster_ip="None",
                    selector=labels,
                    ports=[client.V1ServicePort(
                        port=service_port,
                        target_port=service_target_port
                    )]
                )
            )

            image_pull_secrets = [client.V1LocalObjectReference(name=registry_auth)] if registry_auth else None
            self.core_api.create_namespaced_service(namespace=namespace, body=svc_body)
            sts_body = client.V1StatefulSet(
                api_version="apps/v1",
                kind="StatefulSet",
                metadata=client.V1ObjectMeta(name=name),
                spec=client.V1StatefulSetSpec(
                    replicas=replicas,
                    service_name=name,
                    selector=client.V1LabelSelector(
                        match_labels=labels
                    ),
                    template=client.V1PodTemplateSpec(
                        metadata=client.V1ObjectMeta(labels=labels),
                        spec=client.V1PodSpec(
                            image_pull_secrets=image_pull_secrets,
                            containers=[client.V1Container(
                                name="container",
                                image=image,
                                command=command
                            )]
                        )
                    )
                )
            )
            self.apps_api.create_namespaced_stateful_set(namespace=namespace, body=sts_body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "statefulset已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def delete(self,request):
        # 删除
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data['namespace']
        try:
            self.apps_api.delete_namespaced_stateful_set(namespace=namespace, name=name)
            code = 200
            msg = "删除成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "删除失败！%s" %e
            code = 500
        result = {'code': code, 'msg': msg}
        return JsonResponse(result)
    def put(self,request):
        pass


class pod_api(View):

    k8s.load_auth_config()
    core_api = client.CoreV1Api()

    def get(self,request):
        search_key = request.GET.get('query')
        namespace = request.GET.get('namespace')

        data = []
        try:
            for item in self.core_api.list_namespaced_pod(namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                labels = item.metadata.labels
                pod_ip = item.status.pod_ip

                containers = []
                status = "None"
                # 只为None说明Pod没有创建（不能调度或者正在下载镜像）
                if item.status.container_statuses is None:
                    status = item.status.conditions[-1].reason
                else:
                    for c in item.status.container_statuses:
                        c_name = c.name
                        c_image = c.image

                        # 获取重启次数
                        restart_count = c.restart_count

                        # 获取容器状态
                        c_status = "None"
                        if c.ready is True:
                            c_status = "Running"
                        elif c.ready is False:
                            if c.state.waiting is not None:
                                c_status = c.state.waiting.reason
                            elif c.state.terminated is not None:
                                c_status = c.state.terminated.reason
                            elif c.state.last_state.terminated is not None:
                                c_status = c.last_state.terminated.reason

                        c = {'c_name': c_name, 'c_image': c_image, 'restart_count': restart_count, 'c_status': c_status}
                        containers.append(c)

                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                d = {"name": name, "namespace": namespace, "pod_ip": pod_ip,
                      "labels": labels, "containers": containers, "status": status,
                      "create_time": create_time}
                if search_key:
                    if search_key in name:  # 实现模糊匹配
                        data.append(d)
                else:
                    data.append(d)
            code = 200
            msg = "查询成功"
        except Exception as e:
            msg = "查询失败！%s" %e
            code = 500
        count = len(data)
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize',10))   # 当前页的数据数量
        start = (page - 1) * limit  # 获取切片的起始值
        end = page * limit # 获取切片的结束值
        data = data[start:end]

        res = {'code': code, 'msg': msg, 'count': count, 'data': data}
        return JsonResponse(res)
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data["name"]
        namespace = data["namespace"]
        image = data["image"]
        registry_auth = data["registry_auth"]
        command = data["command"]
        command = command.split() if command else None
        # 处理标签
        labels = {}
        if data["labels"]:
            try:
                for l in data["labels"].split(","):
                    k = l.split("=")[0]
                    v = l.split("=")[1]
                    labels[k] = v
            except Exception as e:
                res = {"code": 500, "msg": "标签格式错误！"}
                return JsonResponse(res)

        try:
            image_pull_secrets = [client.V1LocalObjectReference(name=registry_auth)] if registry_auth else None
            body = client.V1Pod(
                api_version="v1",
                kind="Pod",
                metadata=client.V1ObjectMeta(
                    name=name,
                    labels=labels
                ),
                spec=client.V1PodSpec(
                    image_pull_secrets=image_pull_secrets,
                    containers=[
                        client.V1Container(
                            name='container',
                            image=image,
                            command=command
                        )
                    ]
                )
            )
            self.core_api.create_namespaced_pod(namespace=namespace, body=body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "pod已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        res = {'code': code, 'msg': msg}
        return JsonResponse(res)
    def delete(self,request):
        # 删除
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data['namespace']
        try:
            self.core_api.delete_namespaced_pod(namespace=namespace, name=name)
            code = 200
            msg = "删除成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "删除失败！%s" %e
            code = 500
        result = {'code': code, 'msg': msg}
        return JsonResponse(result)
    def put(self,request):
        # 更新
        pass


class deployment_details(View):

    k8s.load_auth_config()
    core_api = client.CoreV1Api()
    apps_api = client.AppsV1Api()
    networking_api = client.NetworkingV1Api()

    def get(self,request):
        dp_name = request.GET.get("name")
        namespace = request.GET.get("namespace")
        try:
            for dp in self.apps_api.list_namespaced_deployment(namespace=namespace).items:
                if dp_name == dp.metadata.name:
                    # 基本信息
                    name = dp.metadata.name
                    namespace = dp.metadata.namespace
                    replicas = dp.spec.replicas
                    available_replicas = (
                        0 if dp.status.available_replicas is None else dp.status.available_replicas)  # ready_replicas
                    labels = dp.metadata.labels
                    selector = dp.spec.selector.match_labels

                    # 通过deployment反查对应service
                    service = []
                    ports_list = []
                    svc_name = None
                    for svc in self.core_api.list_namespaced_service(namespace=namespace).items:
                        if svc.spec.selector == selector:
                            svc_name = svc.metadata.name  # 通过该名称筛选ingress
                            type = svc.spec.type
                            cluster_ip = svc.spec.cluster_ip
                            ports = svc.spec.ports
                            for i in ports:
                                ports_obj = {"name":i.name,"node_port":i.node_port,"port":i.port,"protocol":i.protocol,"target_port":i.target_port}
                                ports_list.append(ports_obj)
                            data = {"type": type, "cluster_ip": cluster_ip, "ports": ports_list}
                            service.append(data)

                    # service没有创建，ingress也就没有  ingress->service->deployment->pod
                    ingress = {"rules": None, "tls": None}
                    ingress_list = []
                    for ing in self.networking_api.list_namespaced_ingress(namespace=namespace).items:
                        for r in ing.spec.rules:
                            for b in r.http.paths:
                                if b.backend.service.name == svc_name:
                                    if ing.spec.rules:
                                        for i in ing.spec.rules:
                                            rules_obj = {"host":i.host,"path":i.http.paths[0].path,
                                                         "service_name":i.http.paths[0].backend.service.name,
                                                         "service_port":i.http.paths[0].backend.service.port.number
                                                         }
                                            ingress_list.append(rules_obj)
                                            ingress['rules'] = ingress_list
                                    if ing.spec.tls:
                                        for i in ing.spec.tls:
                                            tls_obj = {"hosts":i.hosts,"secret_name":i.secret_name}
                                            ingress_list.append(tls_obj)
                                            ingress["tls"] = ingress_list

                    containers = []
                    for c in dp.spec.template.spec.containers:
                        c_name = c.name
                        image = c.image
                        liveness_probe = c.liveness_probe
                        if liveness_probe:
                            if liveness_probe.http_get:
                                liveness_probe = {"http_get":"http_get","path":c.liveness_probe.http_get.path,"port":c.liveness_probe.http_get.port,
                                                      "scheme":c.liveness_probe.http_get.scheme,"initial_delay_seconds":c.liveness_probe.initial_delay_seconds,
                                                      "period_seconds":c.liveness_probe.period_seconds}
                            elif liveness_probe.tcp_socket:
                                liveness_probe = {"tcp_socket":"tcp_socket","port":c.liveness_probe.tcp_socket.port,
                                                      "initial_delay_seconds":c.liveness_probe.initial_delay_seconds,
                                                      "period_seconds":c.liveness_probe.period_seconds}
                            else:
                                liveness_probe = None
                        else:
                            liveness_probe = None
                        readiness_probe = c.readiness_probe
                        if readiness_probe:
                            if readiness_probe.http_get:
                                readiness_probe = {"http_get":"http_get","path":c.readiness_probe.http_get.path,"port":c.readiness_probe.http_get.port,
                                                      "scheme":c.readiness_probe.http_get.scheme,"initial_delay_seconds":c.readiness_probe.initial_delay_seconds,
                                                      "period_seconds":c.readiness_probe.period_seconds}
                            elif readiness_probe.tcp_socket:
                                readiness_probe = {"tcp_socket":"tcp_socket","port":c.readiness_probe.tcp_socket.port,
                                                      "initial_delay_seconds":c.readiness_probe.initial_delay_seconds,
                                                      "period_seconds":c.readiness_probe.period_seconds}
                            else:
                                readiness_probe = None
                        else:
                            readiness_probe = None
                        resources = c.resources  # 在前端处理
                        resources_obj = {'limits': {"cpu":None,"memory":None},"requests":{"cpu":None,"memory":None}}
                        if resources:
                            if resources.limits:
                                if 'cpu' in resources.limits:
                                    resources_obj['limits']['cpu'] = resources.limits['cpu']
                                if 'memory' in resources.limits:
                                    resources_obj['limits']['memory'] = resources.limits['memory']
                            if resources.requests:
                                if 'cpu' in resources.requests:
                                    resources_obj['requests']['cpu'] = resources.requests['cpu']
                                if 'memory' in resources.requests:
                                    resources_obj['requests']['memory'] = resources.requests['memory']
                        else:
                            resources_obj = None
                        env = c.env
                        env_list = []
                        if env:
                            for i in env:
                                env_obj = {"name": i.name,"value":i.value,"value_from":i.value_from}
                                env_list.append(env_obj)
                        else:
                            env_list = None
                        ports = c.ports
                        ports_list = []
                        if ports:
                            for i in ports:
                                port_obj = {"name": i.name, "container_port": i.container_port, "protocol": i.protocol}
                                ports_list.append(port_obj)
                        else:
                            ports_list = None
                        volume_mounts = c.volume_mounts
                        volume_mounts_list = []
                        if volume_mounts:
                            for i in volume_mounts:
                                volume_obj = {"name":i.name, "mount_path":i.mount_path,"sub_path":i.sub_path,"read_only":i.read_only}
                                volume_mounts_list.append(volume_obj)
                        else:
                            volume_mounts_list = None
                        args = c.args
                        command = c.command

                        container = {"name": c_name, "image": image, "liveness_probe": liveness_probe,
                                     "readiness_probe": readiness_probe,"resources": resources_obj,
                                     "env": env_list, "ports": ports_list,"volume_mounts": volume_mounts_list,
                                     "args": args, "command": command
                                    }
                        containers.append(container)

                    tolerations = dp.spec.template.spec.tolerations
                    tolerations_list = []
                    if tolerations:
                        for i in tolerations:
                            tolerations_obj ={"effect":i.effect,"key":i.key,"operator":i.operator,
                                              "toleration_seconds":i.toleration_seconds,"value":i.value}
                            tolerations_list.append(tolerations_obj)
                    else:
                        tolerations_list = None

                    rolling_update_obj = dp.spec.strategy.rolling_update
                    if rolling_update_obj:
                        rolling_update = {"max_surge":rolling_update_obj.max_surge,"max_unavailable":rolling_update_obj.max_unavailable}
                    else:
                        rolling_update = None
                    volumes = []
                    if dp.spec.template.spec.volumes is not None:
                        for v in dp.spec.template.spec.volumes:
                            volume = {}
                            if v.config_map is not None:
                                config_map_obj = {"name":v.config_map.name,"type":"config_map"}
                                volume["config_map"] = config_map_obj
                            elif v.secret is not None:
                                secret_obj = {"name":v.secret.name,"type":"secret"}
                                volume["secret"] = secret_obj
                            elif v.empty_dir is not None:
                                empty_dir_obj = {"name":v.empty_dir.name,"type":"empty_dir"}
                                volume["empty_dir"] = empty_dir_obj
                            elif v.host_path is not None:
                                host_path_obj = {"name":v.host_path.name,"type":"host_path"}
                                volume["host_path"] = host_path_obj
                            elif v.config_map is not None:
                                downward_api_obj = {"name":v.downward_api.name,"type":"downward_api"}
                                volume["downward_api"] = downward_api_obj
                            elif v.config_map is not None:
                                glusterfs_obj = {"name":v.glusterfs.name,"type":"glusterfs"}
                                volume["glusterfs"] = glusterfs_obj
                            elif v.cephfs is not None:
                                cephfs_obj = {"name":v.cephfs.name,"type":"cephfs"}
                                volume["cephfs"] = cephfs_obj
                            elif v.rbd is not None:
                                rbd_obj = {"name":v.rbd.name,"type":"rbd"}
                                volume["rbd"] = rbd_obj
                            elif v.persistent_volume_claim is not None:
                                persistent_volume_claim_obj = {"name":v.persistent_volume_claim.claim_name,"type":"persistent_volume_claim"}
                                volume["persistent_volume_claim"] = persistent_volume_claim_obj
                            else:
                                volume["unknown"] = "unknown"
                            volumes.append(volume)

                    rs_number = dp.spec.revision_history_limit
                    create_time = k8s.timestamp_format(dp.metadata.creation_timestamp)

                    dp_info = {"name": name, "namespace": namespace, "replicas": replicas,
                               "available_replicas": available_replicas, "labels": labels,
                               "selector": selector, "containers": containers, "rs_number": rs_number,
                               "rolling_update": rolling_update, "create_time": create_time, "volumes": volumes,
                               "tolerations": tolerations_list, "service": service, "ingress": ingress}
                    code = 200
                    msg = '获取成功'
                    res = {'code': code, 'msg': msg, 'data': dp_info}
                    return JsonResponse(res)
        except Exception as e:
            code = 500
            msg = '获取失败： %s' %e
            res = {'code': code, 'msg': msg}
            return JsonResponse(res)


class replicaset_api(View):

    k8s.load_auth_config()
    apps_api = client.AppsV1Api()

    def get(self,request):
        dp_name = request.GET.get("name")
        namespace = request.GET.get("namespace")
        data = []
        for item in self.apps_api.list_namespaced_replica_set(namespace=namespace).items:
            current_dp_name = item.metadata.owner_references[0].name
            rs_name = item.metadata.name
            if dp_name == current_dp_name:
                namespace = item.metadata.namespace
                replicas = item.status.replicas
                available_replicas = item.status.available_replicas
                ready_replicas = item.status.ready_replicas
                revision = item.metadata.annotations["deployment.kubernetes.io/revision"]
                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                containers = {}
                for c in item.spec.template.spec.containers:
                    containers[c.name] = c.image

                d = {"name": rs_name, "namespace": namespace, "replicas": replicas,
                        "available_replicas": available_replicas, "ready_replicas": ready_replicas,
                        "revision":revision, 'containers': containers, "create_time": create_time}
                data.append(d)
        count = len(data) # 可选，rs默认保存10条，所以不用分页
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize', 10))  # 当前页的数据数量
        start = (page - 1) * limit
        end = page * limit
        data = data[start:end]

        res = {"code": 200, "msg": "获取成功", "count": count, 'data': data}
        return JsonResponse(res)
    # 回滚
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        dp_name = data['name']
        namespace = data['namespace']
        revision = data['revision']
        print(dp_name,namespace,revision,222)
        # 回滚，参考 https://github.com/kubernetes-client/python/issues/1232
        # 列出命名空间中的RS
        try:
            associated_replica_sets = self.apps_api.list_namespaced_replica_set(
                namespace=namespace,
            )
            # 按修订版本排序RS
            revision_ordered_replica_sets = sorted(
                associated_replica_sets.items,
                key=lambda e: e.metadata.annotations['deployment.kubernetes.io/revision'],
                reverse=True
            )
            # 查看目标修订版本的RS
            idx = 0
            for i in revision_ordered_replica_sets:
                idx += 1
                for k, v in i.metadata.annotations.items():
                    if (k == "deployment.kubernetes.io/revision" and v == revision):
                        break
            rollback_replica_set = (
                revision_ordered_replica_sets[idx - 1]
            )
            patch = [
                {
                    'op': 'replace',
                    'path': '/spec/template',
                    'value': rollback_replica_set.spec.template
                },
                {
                    'op': 'replace',
                    'path': '/metadata/annotations',
                    'value': {
                        'deployment.kubernetes.io/revision': revision,
                    }
                }
            ]

            self.apps_api.patch_namespaced_deployment(name=dp_name, namespace=namespace, body=patch)
            code = 200
            msg = "回滚成功！"
        except Exception as e:
            print(e)
            msg = "回滚失败！%s" %e
            code = 500
        res = {"code": code, "msg": msg}
        return JsonResponse(res)